const middleWares = [
  next => {
    console.log(1)
    next()
    console.log(2)
  },
  next => {
    console.log(3)
    next()
    console.log(4)
  }
]

const fn = compose(middleWares)

fn()

function assert(condition, msg) {
  if (!condition) {
    throw new Error(msg)
  }
}

function compose(array) {
  array = Array.isArray(array) ? array : [array]
  assert(
    array.every(it => typeof it == 'function'),
    'compose item must be funtion'
  )
  let i = 0
  const fn = async () => {
    return await array[i](nextFn)
  }
  const nextFn = async () => {
    return ++i < array.length ? await fn() : null
  }
  return async () => {
    return await fn()
  }
}
